<?php
/**
 * Created by PhpStorm.
 * User: stupboy
 * Date: 2018/2/6
 * Time: 22:16
 */

namespace app\cron\model;

use app\base\service\Redis;
use think\Model;

class Driver extends Model
{
    public function getOnWorkDriver(){
        $redis         = new \Redis();
        $redisConfig   = Config('database.redis');
        $appPrefix     = $redisConfig ['prefix'];
        $redis->connect($redisConfig['host'],$redisConfig['port']);
        $driverList    = $redis->hVals($appPrefix.'driver.4.login');
        $list = [];
        foreach ($driverList as $v) {
            $driver = unserialize($v);
            if($driver['work_state']==  4) continue;// 司机状态过滤
            if(time() - $driver['gps_time']>3000000) continue;// 30秒 未定位不派单
            $temp['driver_id']  = $driver['driver_id'];
            $temp['lon']        = $driver['lon'];
            $temp['lat']        = $driver['lat'];
            $temp['work_state'] = $driver['work_state'];
            $temp['car_id']     = $driver['car_id'];
            $temp['car_type_id']= $driver['car_type_id'];
            $temp['other_type'] = $driver['other_type'];
            $list[] = $temp;
        }
        return $list;
    }

    public function getAllDriver(){
        $where['work_state'] = ['in','2,3'];
        $where['user_id']    = ['>', 0];
        $field  = 'a.driver_id,c.car_type_id,c.type,c.car_type,a.lon,a.lat,a.update_time';
        $list   = $this->alias('a')
            ->join('car b','a.car_id = b.car_id','left')
            ->join('car_type c','b.car_type_id = c.car_type_id','left')
            ->field($field)
            ->where($where)->select();
        return $list;
    }

    public function getNearDriver($drivers,$order){
        $newDriver = [];
        foreach($drivers as $driver){
            if($driver['car_type_id']==$order['car_type_id']){
                $driver['distance'] = getDistance($driver['lon'],$driver['lat'],$order['lon'],$order['lat']);
                $newDriver[] = $driver;
            }
        }

    }

    /**
     * 根据GPS坐标获取范围内最近的司机
     * @param $order
     * @param $lonMin
     * @param $lonMax
     * @param $latMin
     * @param $latMax
     * @param int $car_type
     * @param int $type
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getNearDriverByGps($order,$lonMin, $lonMax, $latMin, $latMax,$car_type=0,$type=1){
        $lon                 = $order['from_lon'];
        $lat                 = $order['from_lat'];
        $where['lon']        = ['between', "$lonMin,$lonMax"];
        $where['lat']        = ['between', "$latMin,$latMax"];
        $where['user_id']    = ['>', 0];
        $where['work_state'] = ['in','2,3'];
        $where['c.type']     = $type;
        $where['c.car_type'] = $car_type;
        $drivers = $this->alias('a')
            ->join('car b','a.car_id = b.car_id','left')
            ->join('car_type c','b.car_type_id = c.car_type_id','left')
            ->where($where)
            ->field('a.user_id,a.driver_id,b.car_type_id,a.lon,a.lat')
            ->select();
        $newDrivers  = [];
        $distanceArr = [];
        foreach ($drivers as $driver){
            $driver['distance'] = getGpsDistance($lon,$lat,$driver['lon'],$driver['lat']);
            $distanceArr        = $driver['distance'];
            $newDrivers[]       = $driver;
        }
        // 根据距离排序
        array_multisort($distanceArr,SORT_ASC,SORT_NUMERIC,$newDrivers);
        return $newDrivers;
    }

    /**
     * 从缓存REDIS获取附近司机
     * @param $order
     * @param $lonMin
     * @param $lonMax
     * @param $latMin
     * @param $latMax
     * @param int $car_type
     * @param int $type
     * @param int $limit 0普通 1四办 2行政执法
     * @return array
     */
    public function getNearDriverByGpsRedis($order,$lonMin, $lonMax, $latMin, $latMax,$car_type=0,$type=1,$limit=0){
        $redis       = Redis::getInstance();
        $arr         = $redis->hScanYield('car.driver.4.login','*');
        $carTypeStr  = $type.'-'.$car_type;
        $drivers     = [];
        $driversSpare= [];
        $distanceArr = [];
        $distanceArr2= [];
        $nowTime     = time();
        foreach ($arr as $v){
            $driver    = unserialize($v);
            // 必须是听单状态
            if(!in_array($driver['work_state'],[2,3])) continue;
            // id 必须大于0
            if($driver['user_id']==0) continue;
            // GPS定位时间不超过1分钟
            if($nowTime - $driver['gps_time']/1000>60) continue;
            // 经纬度过滤
            if($latMin > $driver['lat'] || $driver['lat'] > $latMax ) continue;
            if($lonMin > $driver['lon'] || $driver['lon'] > $lonMax ) continue;
            $carTypes    = $driver['car_types'];
            // 特殊类型 过滤
            $limitResult = $this->checkLimit($driver,$limit);
            // 车型匹配
            if($driver['default_car_type'] ==$carTypeStr && $limitResult){
                $driver['distance'] = getGpsDistance($order['from_lon'],$order['from_lat'],$driver['lon'],$driver['lat']);
                $distanceArr[]      = $driver['distance'];
                $driver['rece_car'] = $carTypes[$carTypeStr];
                $drivers[]          = $driver;
                continue;
            }
            // 没有其他车型则跳过检查
            if(count($driver['car_types'])<2) continue;
            // 特殊类型 过滤
            $limitResult = $this->checkSpareLimit($driver,$limit,$carTypeStr);
            // 备选车型过滤
            if(array_key_exists($carTypeStr,$carTypes) && $limitResult){
                $driver['distance'] = getGpsDistance($order['from_lon'],$order['from_lat'],$driver['lon'],$driver['lat']);
                $distanceArr2[]     = $driver['distance'];
                $driver['rece_car'] = $carTypes[$carTypeStr];//接单车辆
                $driversSpare[]     = $driver;
            }
        }
        // 根据距离排升序
        array_multisort($distanceArr,SORT_ASC,SORT_NUMERIC,$drivers);
        // 备选车型存在时排升序
        !empty($driversSpare) && array_multisort($distanceArr2,SORT_ASC,SORT_NUMERIC,$driversSpare);
        return [$drivers,$driversSpare];
    }

    /**
     * 默认车型过滤
     * @param $driver
     * @param $type
     * @return bool
     */
    public function checkLimit($driver,$type){
        if($type==0){
            // 普通用车过滤4办及行政执法车辆
            $prop = $driver['default_prop'] ? intval($driver['default_prop']) :0 ;
            if($prop>2){
                return false;
            }
            return true;
        }
        if($type==2 && $driver['default_prop'] == 3) return true;//行政执法
        if($type==3 && $driver['default_prop'] == 4) return true;//四办
        return false;
    }

    /**
     * 备选车型过滤
     * @param $driver
     * @param $limit
     * @param $type
     * @return bool
     */
    public function checkSpareLimit($driver,$limit,$type){
        $car1 = []; $car2 = [];
        // 过滤非行政执法车辆
        if($limit==0){
            $car1 = [];
            foreach ($driver['prop'] as $k=>$v){
                $prop = $k ? intval($k) : 0;
                if($prop>2){

                }else{
                    $car1[] = $v;
                }
            }
            $car2 = [];
            foreach ($driver['car_types'] as $k=>$v){
                if($k==$type){
                    $car2[] = $v;
                }
            }
        }
        // 检测车型 及 行政执法属性是否同时满足
        if($limit==2){
            $car1 = [];
            foreach ($driver['prop'] as $k=>$v){
                if($k==3){
                    $car1[] = $v;
                }
            }
            $car2 = [];
            foreach ($driver['car_types'] as $k=>$v){
                if($k==$type){
                    $car2[] = $v;
                }
            }
        }
        // 检测车型 及 四办属性是否同时满足
        if($limit==3){
            $car1 = [];
            foreach ($driver['prop'] as $k=>$v){
                if($k==4){
                    $car1[] = $v;
                }
            }
            $car2 = [];
            foreach ($driver['car_types'] as $k=>$v){
                if($k==$type){
                    $car2[] = $v;
                }
            }
        }
        $disArr = array_intersect($car1,$car2);
        if(!empty($car1) && !empty($car2) && !empty($disArr)) return true;
        return false;
    }
}